#ifndef __CWALL_H__
#define __CWALL_H__     // (See #endif at the very end of this file).
//==============================================================================
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_
//                               (why all the numbers? I prefer 80-column text)
//
//      CWall.h     Our constraint-making object class
//          'wall-vectors' in CPartSys == dyn. alloc'd arrays of CWall objects;
//                       See bottom of CPartSys.h for detailed explanation.
//==============================================================================

// multi-platform includes for the GLUT/OpenGL libraries:-----------------------
#if defined(_WIN32)
#include <GL\glew.h>    // OpenGL 'extensions wrangler' for easy access.
#include <GL\freeglut.h>// open-source GLUT functions for windows, keybd, mouse
/*---*OR*--- use:
// #include <GL/glut.h> // for 100% backwards-compatibility with Mark Kilgard's
                        // SGI-copyrighted GLUT library. Careful! this excludes
                        // freeglut's callbacks for mouse wheel, etc.
*/
/*
// freeglut.h already contains these other includes that were necessary for
// using Kilgard's original GLUT library:
#include <GL/GL.h>          // OpenGL 3D graphics rendering functions
#include <GL/Glu.h>         // OpenGL utilties functions
#include <GL/glext.h>       // #defines for all OpenGL features on your machine.
*/
#elif defined(__APPLE__)
#include <GLUT/glut.h>      // GLUT functions for windows, keybd, mouse
#include <OpenGL/GL.h>      // OpenGL 3D graphics rendering functions
#include <OpenGL/Glu.h>     // OpenGL utilties functions
#include <OpenGL/GLext.h>   // #defines for all OpenGL features on your machine.
// UNIX, Linux of all flavors;
#else
#include <unistd.h>         // defines symbolic constants, POSIX versions, etc.
#include <GL/glew.h>        // OpenGL 'extensions wrangler' for 'mesa' lib usage
#include <GL/freeglut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#endif
//-----------------------------end multi-platform includes for GLUT/OpenGL------

// CWall::wallType values;
//-------------------------------
// a) Specifies the type of constraint implemented by each CWall object, and
// b) gives you an easy way to enable/disable each constraint object:
//      partType >0 == active; partType < 0 == temporarily disabled;
//      Just reverse the sign of CWall::wallType to enable/disable an object.
// (an easier/faster way to vary the number of particles without resorting to
//  memory allocation/de-allocation.  Also useful for debugging).
//-----------------------
// EXHAUSTIVELY LONG LIST!  Implement what you like, ignore the rest.
//-----------------------
#define WTYPE_DEAD      0   // DEAD CONSTRAINT!!!  Abandoned, not in use, no
                            // meaningful values, available for re-use.
// Most-Basic constraints;
//----------------------------
#define WTYPE_GROUND    1   // y=0 ground-plane; Kbouncy=0; keeps particle y>=0.
#define WTYPE_XWALL_LO  2   // planar X wall; keeps particles >= xmin
#define WTYPE_XWALL_HI  3   // planar X wall; keeps particles <= xmax
#define WTYPE_YWALL_LO  4   // planar Y wall; keeps particles >= ymin
#define WTYPE_YWALL_HI  5   // planar Y wall; keeps particles <= ymax
#define WTYPE_ZWALL_LO  6   // planar Z wall; keeps particles >= zmin
#define WTYPE_ZWALL_HI  7   // planar Z wall; keeps particles <= zmax
#define WTYPE_WALL_GEN  8   // Generic wall; thru point xpos,ypos,zpos; stay on
                            // same side as surface normal vector nx,ny,nz.
// distance constraints
//----------------------------
#define WTYPE_STICK     9   // Connects 2 particles with fixed-length separation
#define WTYPE_PULLEY   10   // Keep constant sum-of-distances for 3 particles
                            // A,B,Pivot:  ||A-Pivot||+||B-Pivot|| = dmax.
#define WTYPE_ANCHOR   11   // Lock one particle at location xpos,ypos,zpos

// volume constraints;
//---------------------------
    // solid shapes; keeps particles OUTSIDE:
#define WTYPE_VBOX_OUT  12  // solid box; (xmin,xmax,ymin,ymax,zmin,zmax)
#define WTYPE_VBALL_OUT 13  // solid sphere at xpos,ypos,zpos; radius radmin
#define WTYPE_VCYL_OUT  14  // solid cylinder at xpos,ypos,zpos; radius radmin,
                            // cylinder length dmin, along direction nx,ny,nz
#define WTYPE_VMESH_OUT 15  // solid shape formed by vertex buffer object...
    // hollow shapes; keeps particles INSIDE:
#define WTYPE_VBOX_IN   16  // hollow box; (xmin,xmax,ymin,ymax,zmin,zmax)
#define WTYPE_VBALL_IN  17  // hollow sphere at xpos,ypos,zpos, radius dmax
#define WTYPE_VCYL_IN   18  // solid cylinder at xpos,ypos,zpos; radius radmax,
                            // cylinder length dmax
#define WTYPE_VMESH_IN  19  // hollow shape formed by vertex buffer object....

// surface constraints; restrict particles to surface of a shape:
//----------------------------
#define WTYPE_SPLANE    20  // Plane thru point xpos,ypos,zpos; normal nx,ny,nz
#define WTYPE_SDISK     21  // circular disk,radius radmax, in plane thru point
                            // xpos,ypos,zpos with surface normal nx,ny,nz.
#define WTYPE_SBOX      22  // surface of box (xmin,xmax,ymin,ymax,zmin,zmax)
#define WTYPE_SBALL     23  // surface of sphere at xpos,ypos,zpos;radius radmax
#define WTYPE_SCYL      24  // solid cylinder at xpos,ypos,zpos; radius radmax,
                            // cylinder length dmax, along direction nx,ny,nz
#define WTYPE_SMESH     25  // lock selected particles to a VBO's surface

// Line constraints; restrict particles to a 1-D path in 3D
//----------------------------
#define WTYPE_SLOT      26   // line thru point xpos,ypos,zpos in direction of
                            // normal vector nx,ny,nz, length dmax.
#define WTYPE_MAXVAR    27   // Number of CPart particle types available.


class CWall
//==============================================================================
{
public:
    CWall(void);                 // Default constructor/destructor
    ~CWall(void);

    int wallType;           // Constraint type; not required, but a) helps you
                            // identify the intended purpose of each constraint,
                            // and b) gives you an easy way to enable/disable
                            // each constraint:
                            //  wallType  >0 == active constraint; use it! the
                            //                   value describes its use
                            //  wallType ==0 == 'dead' constraint, abandoned,
                            //                  ignored, available for re-use.
                            //  wallType  <0 == temporarily disabled 'frozen';
                            //                  to re-enable this particle,
                            //                  set wallType = -wallType;
    double Kbouncy;         // Coeff. of restoration for constraint surfaces:
                            // Particles moving at speed ||V|| will bounce off
                            // a constraint surface and lose some energy; after
                            // the bounce, speed is ||V||*Kbouncy.
                            //   0.0 <= Kbouncy <= 1.0;     'no bounce'== 0.0;
                            //                          'perfect bounce'==1.0.
    // Some, not all of values below used for some, not all of the many types
    // of constraints we can select by setting wallType value.
    double xpos,ypos,zpos;  // 3D position value
    double xmin,xmax,ymin,ymax,zmin,zmax;   // min/max 3D positions
    double nx,ny,nz;        // 3D surface normal vector value
    double dmin,dmax;       // minimum, maximum distance value
    double radmin,radmax;   // minimum, maximum radius for sphere, cyl, circle
    double thetamin,thetamax;   // min, max angle for rotations.

    // Array indices of all affected particles
    int partSetSize;        // How many particle-numbers stored at pPartSet
    int *pPartSet;          // Dyn. alloc'd array of particle-numbers for all
                            // the particles affected by this constraint.
                            // Each element 'i' in the pPartSet[i] array
                            // refers to one particle in the state vectors of
                            // CPartSys, which are arrays of CPart objects.
                            //    For example,
                            // mySys.pS0[] is the dyn. alloc'd array of CPart
                            //      particle objects that make up the current
                            //      state-vector s0, and
                            //  mySys.pC0[] is the dyn. alloc'd array of CWall
                            //      constraint objects that make up the current
                            //      wall-vector (or 'constraint vector) w0, then
                            //  This constraint object:   mySys.pC0[3]
                            //      affects mySys.pC0[3].partSetSize particles
                            //      in the mySys.pS0[] array, and
                            //  to find i-th affected CPart particle, use:
                            //      mySys.pS0[ pPartSet[i] ]
                            //          where 0 <= i < partSetSize.
};

#endif // CWALL_H
